﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Reflection;
using System.Web.Mvc;

using BOSS.Framework.Search;
using BOSS.Framework.Search.Result;
using BOSS.Framework.Search.Context;
using BOSS.Domain.Security;
using BOSS.Service.Security;
using BOSS.Web.ViewDatas;

namespace BOSS.Web
{
    /// <summary>
    /// 控制器的抽象基类。默认提供 全局配置服务、帐号服务、安全服务、搜索服务
    /// </summary>
    public abstract class AbstractController : Controller
    {
        #region 注入属性

        /// <summary>
        /// 获取 / 设置 全局配置服务
        /// </summary>
        //public IGlobalConfigurationService GlobalConfigurationService { get; set; }

        /// <summary>
        /// 获取 / 设置 帐号服务
        /// </summary>
        public IAccountService AccountService { get; set; }

        /// <summary>
        /// 获取 / 设置 安全服务
        /// </summary>
        //public ISecurityService SecurityService { get; set; }

        /// <summary>
        /// 获取 / 设置 搜索服务
        /// </summary>
        public ISearchService SearchService { get; set; }

        #endregion

        private static readonly string version;

        /// <summary>
        /// 静态构造函数
        /// </summary>
        static AbstractController()
        {
            // 获取版本号标识
            Assembly assembly = Assembly.GetExecutingAssembly();
            string productVersion = null;
            object[] customerAttributes = assembly.GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false);
            if ((customerAttributes != null) && (customerAttributes.Length > 0))
            {
                productVersion = ((AssemblyInformationalVersionAttribute)customerAttributes[0]).InformationalVersion;
            }

            if (string.IsNullOrEmpty(productVersion))
            {
                version = assembly.GetName().Version.ToString();
            }
            else
            {
                version = string.Format("{0} ({1})", assembly.GetName().Version, productVersion);
            }

        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <param name="requestContext"></param>
        protected override void Initialize(System.Web.Routing.RequestContext requestContext)
        {
            base.Initialize(requestContext);
            ViewData["Version"] = version;

            string domain = RequestUrlHelper.GetDomain(requestContext.HttpContext.Request);
            this.CheckDomain(domain, requestContext);
        }

        /// <summary>
        /// 检查域名
        /// </summary>
        /// <param name="domain"></param>
        /// <param name="requestContext"></param>
        protected virtual void CheckDomain(string domain, System.Web.Routing.RequestContext requestContext)
        {
            // 若指定了域名，则跳转到系统默认首页
            if (!string.IsNullOrEmpty(domain))
            {
                this.Response.Redirect(RequestUrlHelper.BuildHomepageUrl());
            }
        }

        /// <summary>
        /// 页面许可
        /// </summary>
        private IDictionary<string, bool> m_permissions;

        /// <summary>
        /// 设置页面许可
        /// </summary>
        /// <param name="name"></param>
        /// <param name="allow"></param>
        protected void SetPermission(string name, bool allow)
        {
            if (this.m_permissions == null)
            {
                this.m_permissions = new Dictionary<string, bool>();
                ViewData[ViewDataConstants.PERMISSIONS] = this.m_permissions;
            }
            this.m_permissions[name] = allow;
        }

        /// <summary>
        /// 获取 / 设置 页面标题
        /// </summary>
        protected string PageTitle
        {
            get
            {
                var value = ViewData[ViewDataConstants.PAGE_TITLE];
                if (value == null)
                {
                    return string.Empty;
                }
                else
                {
                    return value.ToString();
                }
            }
            set
            {
                ViewData[ViewDataConstants.PAGE_TITLE] = value;
            }
        }

        /// <summary>
        /// 跳转到指定人员的首页
        /// </summary>
        /// <param name="account"></param>
        /// <returns></returns>
        public ActionResult RedirectToHome(Account account)
        {
            return Redirect(RequestUrlHelper.BuildHomeUrl(account));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="account"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public ActionResult RedirectToHome(Account account, string url)
        {
            return Redirect(RequestUrlHelper.BuildHomeUrl(account, url));
        }

        /// <summary>
        /// 显示搜索结果
        /// </summary>
        /// <param name="viewName"></param>
        /// <param name="contentType"></param>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <returns></returns>
        protected ActionResult ShowSearchResult(string viewName, string contentType, int? start, int? limit)
        {
            return this.ShowSearchResult(viewName, contentType, start, limit, null, null);
        }

        /// <summary>
        /// 显示搜索结果
        /// </summary>
        /// <param name="viewName"></param>
        /// <param name="contentType"></param>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <param name="sort"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        protected ActionResult ShowSearchResult(string viewName, string contentType, int? start, int? limit, string sort, string dir)
        {
            ISearchContext searchContext = this.SearchService.CreateContext(contentType);
            this.TryUpdateModel(searchContext, "q");

            return this.ShowSearchResult(viewName, searchContext, start, limit, sort, dir);
        }


        /// <summary>
        /// 显示搜索结果
        /// </summary>
        /// <param name="viewName"></param>
        /// <param name="searchContext"></param>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <param name="sort"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        protected ActionResult ShowSearchResult(string viewName, ISearchContext searchContext, int? start, int? limit, string sort, string dir)
        {
            if (limit.HasValue)
            {
                searchContext.SetPageSize(limit.Value);
            }
            if (start.HasValue)
            {
                searchContext.SetPageIndex((start.Value / searchContext.PageSize) + 1);
            }
            if (!string.IsNullOrEmpty(sort))
            {
                searchContext.SetSort(sort, "DESC".Equals(dir));
            }

            ISearchResult resultForJson = this.SearchService.Search(searchContext);
            if (resultForJson != null)
            {
                return View(viewName, resultForJson);
            }

            return new EmptyResult();
        }

        /// <summary>
        /// 显示列表结果
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="contentType"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult<T>(string contentType, IEnumerable<T> items)
        {
            return this.ShowListResult<T>("List", "SearchResult", contentType, items);
        }

        /// <summary>
        /// 显示列表结果
        /// </summary>
        /// <param name="searchResult"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult(ISearchResult searchResult)
        {
            return this.ShowListResult("List", "SearchResult", searchResult);
        }

        /// <summary>
        /// 显示列表结果
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="viewName"></param>
        /// <param name="contentType"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult<T>(string viewName, string contentType, IEnumerable<T> items)
        {
            return this.ShowListResult<T>(viewName, "SearchResult", contentType, items);
        }

        /// <summary>
        /// 显示列表结果
        /// </summary>
        /// <param name="viewName"></param>
        /// <param name="searchResult"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult(string viewName, ISearchResult searchResult)
        {
            return this.ShowListResult(viewName, "SearchResult", searchResult);
        }

        /// <summary>
        /// 显示列表结果
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="viewName"></param>
        /// <param name="resultViewName"></param>
        /// <param name="contentType"></param>
        /// <param name="items"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult<T>(string viewName, string resultViewName, string contentType, IEnumerable<T> items)
        {
            CollectionBasedSearchResult<T> searchResult = new CollectionBasedSearchResult<T>(contentType, items);
            searchResult.SetPageSize(items.Count());

            return this.ShowListResult(viewName, resultViewName, searchResult);
        }

        /// <summary>
        /// 显示列表结果
        /// </summary>
        /// <param name="viewName"></param>
        /// <param name="resultViewName"></param>
        /// <param name="searchResult"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult(string viewName, string resultViewName, ISearchResult searchResult)
        {
            ViewData["ListResult"] = searchResult;
            ViewData["ResultView"] = resultViewName;

            if (this.Request.IsPost())
            {
                return View(resultViewName, searchResult);
            }
            else
            {
                return View(viewName);
            }
        }

        /// <summary>
        /// 显示列表结果
        /// </summary>
        /// <param name="viewName"></param>
        /// <param name="resultViewName"></param>
        /// <param name="contentType"></param>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <param name="sort"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult(string viewName, string resultViewName, string contentType, int? start, int? limit, string sort, string dir)
        {
            return this.ShowListResult(viewName, resultViewName, contentType, null, null, null, null, null);
        }

        /// <summary>
        ///  显示列表结果
        /// </summary>
        /// <param name="viewName"></param>
        /// <param name="resultViewName"></param>
        /// <param name="contentType"></param>
        /// <param name="filters"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult(string viewName, string resultViewName, string contentType, IDictionary<string, object> filters)
        {
            return this.ShowListResult(viewName, resultViewName, contentType, filters, null, null, null, null);
        }

        /// <summary>
        ///  显示列表结果
        /// </summary>
        /// <param name="viewName"></param>
        /// <param name="resultViewName"></param>
        /// <param name="contentType"></param>
        /// <param name="filters"></param>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <param name="sort"></param>
        /// <param name="dir"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult(string viewName, string resultViewName, string contentType, IDictionary<string, object> filters, int? start, int? limit, string sort, string dir)
        {
            return this.ShowListResult(viewName, resultViewName, contentType, filters, start, limit, sort, dir, null);
        }

        /// <summary>
        ///  显示列表结果
        /// </summary>
        /// <param name="viewName"></param>
        /// <param name="resultViewName"></param>
        /// <param name="contentType"></param>
        /// <param name="filters"></param>
        /// <param name="start"></param>
        /// <param name="limit"></param>
        /// <param name="sort"></param>
        /// <param name="dir"></param>
        /// <param name="resultFilter"></param>
        /// <returns></returns>
        protected ActionResult ShowListResult(string viewName, string resultViewName, string contentType, IDictionary<string, object> filters, int? start, int? limit, string sort, string dir, Func<object, bool> resultFilter)
        {
            ISearchContext searchContext = this.SearchService.CreateContext(contentType);

            this.TryUpdateModel(searchContext, "q");

            if (filters != null)
            {
                foreach (var item in filters)
                {
                    if (item.Value is RangeDateFilterPart)
                    {
                        if (searchContext.GetFilterRangeMinValueAsDateTime(item.Key) == null && searchContext.GetFilterRangeMaxValueAsDateTime(item.Key) == null)
                        {
                            RangeDateFilterPart rangeDateFilterPart = item.Value as RangeDateFilterPart;
                            searchContext.SetFilter(item.Key, rangeDateFilterPart.MinValue, rangeDateFilterPart.IncludeMinValue, rangeDateFilterPart.MaxValue, rangeDateFilterPart.IncludeMaxValue);
                        }
                    }
                    else if (item.Value is RangeNumberFilterPart)
                    {
                        if (searchContext.GetFilterRangeMinValueAsInt32(item.Key) == null && searchContext.GetFilterRangeMaxValueAsInt32(item.Key) == null)
                        {
                            RangeNumberFilterPart rangeNumberFilterPart = item.Value as RangeNumberFilterPart;
                            searchContext.SetFilter(item.Key, rangeNumberFilterPart.MinValue, rangeNumberFilterPart.IncludeMinValue, rangeNumberFilterPart.MaxValue, rangeNumberFilterPart.IncludeMaxValue);
                        }
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(searchContext.GetFilterTermValueAsString(item.Key)))
                        {
                            searchContext.SetFilter(item.Key, item.Value.ToString());
                        }
                    }
                }
            }

            if (limit.HasValue)
            {
                searchContext.SetPageSize(limit.Value);
            }
            if (start.HasValue)
            {
                searchContext.SetPageIndex((start.Value / searchContext.PageSize) + 1);
            }
            if (!string.IsNullOrEmpty(sort))
            {
                searchContext.SetSort(sort, "DESC".Equals(dir));
            }

            ISearchResult searchResult = this.SearchService.Search(searchContext);
            if (searchResult != null && resultFilter != null)
            {
                searchResult = searchResult.Filter(resultFilter);
            }

            ViewData["ListResult"] = searchResult;
            ViewData["ResultView"] = resultViewName;

            if (this.Request.IsPost())
            {
                return View(resultViewName, searchResult);
            }
            else
            {
                return View(viewName);
            }
        }

        #region 增加文件结果的处理

        /// <summary>
        /// Returns a FilePathResult which writes the file to the response. 
        /// </summary>
        /// <param name="fileName"></param>
        /// <param name="contentType"></param>
        /// <param name="fileDownloadName"></param>
        /// <returns></returns>
        //protected override FilePathResult File(string fileName, string contentType, string fileDownloadName)
        //{
        //    FilePathResult result = new FilePathResultEx(fileName, contentType);
        //    result.FileDownloadName = fileDownloadName;
        //    return result;
        //}

        /// <summary>
        /// Returns a FileContentResult which writes the fileContents to the response.
        /// </summary>
        /// <param name="fileContents"></param>
        /// <param name="contentType"></param>
        /// <param name="fileDownloadName"></param>
        /// <returns></returns>
        //protected override FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName)
        //{
        //    FileContentResult result = new FileContentResultEx(fileContents, contentType);
        //    result.FileDownloadName = fileDownloadName;
        //    return result;
        //}

        /// <summary>
        /// Returns a FileStreamResult which writes the fileStream to the response.
        /// </summary>
        /// <param name="fileStream"></param>
        /// <param name="contentType"></param>
        /// <param name="fileDownloadName"></param>
        /// <returns></returns>
        //protected override FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName)
        //{
        //    FileStreamResult result = new FileStreamResultEx(fileStream, contentType);
        //    result.FileDownloadName = fileDownloadName;
        //    return result;
        //}

        #endregion

        #region 增强 TryUpdateModel 和 UpdateModel

        /*
        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model)
        {
            return this.TryUpdateModel(type, model, null, null, null, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="valueProvider"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model, IDictionary<string, ValueProviderResult> valueProvider)
        {
            return this.TryUpdateModel(type, model, null, null, null, valueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model, string prefix)
        {
            return this.TryUpdateModel(type, model, prefix, null, null, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="includeProperties"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model, string[] includeProperties)
        {
            return this.TryUpdateModel(type, model, null, includeProperties, null, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="includeProperties"></param>
        /// <param name="valueProvider"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model, string[] includeProperties, IDictionary<string, ValueProviderResult> valueProvider)
        {
            return this.TryUpdateModel(type, model, null, includeProperties, null, valueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="includeProperties"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model, string prefix, string[] includeProperties)
        {
            return this.TryUpdateModel(type, model, prefix, includeProperties, null, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="valueProvider"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model, string prefix, IDictionary<string, ValueProviderResult> valueProvider)
        {
            return this.TryUpdateModel(type, model, prefix, null, null, valueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="includeProperties"></param>
        /// <param name="valueProvider"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model, string prefix, string[] includeProperties, IDictionary<string, ValueProviderResult> valueProvider)
        {
            return this.TryUpdateModel(type, model, prefix, includeProperties, null, valueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="includeProperties"></param>
        /// <param name="excludeProperties"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model, string prefix, string[] includeProperties, string[] excludeProperties)
        {
            return this.TryUpdateModel(type, model, prefix, includeProperties, excludeProperties, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="includeProperties"></param>
        /// <param name="excludeProperties"></param>
        /// <param name="valueProvider"></param>
        /// <returns></returns>
        protected bool TryUpdateModel(Type type, object model, string prefix, string[] includeProperties, string[] excludeProperties, IDictionary<string, ValueProviderResult> valueProvider)
        {
            if (model == null)
            {
                throw new ArgumentNullException("model");
            }
            if (valueProvider == null)
            {
                throw new ArgumentNullException("valueProvider");
            }

            if (!type.IsInstanceOfType(model))
            {
                throw new ArgumentException("type 和 model 不兼容。");
            }

            Predicate<string> propertyFilter = propertyName => this.IsPropertyAllowed(propertyName, includeProperties, excludeProperties);
            IModelBinder binder = Binders.GetBinder(type);

            ModelBindingContext bindingContext = new ModelBindingContext()
            {
                Model = model,
                ModelName = prefix,
                ModelState = ModelState,
                ModelType = type,
                PropertyFilter = propertyFilter,
                ValueProvider = valueProvider
            };
            binder.BindModel(ControllerContext, bindingContext);
            return ModelState.IsValid;
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        protected void UpdateModel(Type type, object model)
        {
            this.UpdateModel(type, model, null, null, null, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="valueProvider"></param>
        protected void UpdateModel(Type type, object model, IDictionary<string, ValueProviderResult> valueProvider)
        {
            this.UpdateModel(type, model, null, null, null, valueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        protected void UpdateModel(Type type, object model, string prefix)
        {
            this.UpdateModel(type, model, prefix, null, null, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="includeProperties"></param>
        protected void UpdateModel(Type type, object model, string[] includeProperties)
        {
            this.UpdateModel(type, model, null, includeProperties, null, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="includeProperties"></param>
        /// <param name="valueProvider"></param>
        protected void UpdateModel(Type type, object model, string[] includeProperties, IDictionary<string, ValueProviderResult> valueProvider)
        {
            this.UpdateModel(type, model, null, includeProperties, null, valueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="includeProperties"></param>
        protected void UpdateModel(Type type, object model, string prefix, string[] includeProperties)
        {
            this.UpdateModel(type, model, prefix, includeProperties, null, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="valueProvider"></param>
        protected void UpdateModel(Type type, object model, string prefix, IDictionary<string, ValueProviderResult> valueProvider)
        {
            this.UpdateModel(type, model, prefix, null, null, valueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="includeProperties"></param>
        /// <param name="valueProvider"></param>
        protected void UpdateModel(Type type, object model, string prefix, string[] includeProperties, IDictionary<string, ValueProviderResult> valueProvider)
        {
            this.UpdateModel(type, model, prefix, includeProperties, null, valueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="includeProperties"></param>
        /// <param name="excludeProperties"></param>
        protected void UpdateModel(Type type, object model, string prefix, string[] includeProperties, string[] excludeProperties)
        {
            this.UpdateModel(type, model, prefix, includeProperties, excludeProperties, base.ValueProvider);
        }

        /// <summary>
        /// Updates the specified model instance using values from the Controller's current ValueProvider.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="model"></param>
        /// <param name="prefix"></param>
        /// <param name="includeProperties"></param>
        /// <param name="excludeProperties"></param>
        /// <param name="valueProvider"></param>
        protected void UpdateModel(Type type, object model, string prefix, string[] includeProperties, string[] excludeProperties, IDictionary<string, ValueProviderResult> valueProvider)
        {
            if (!this.TryUpdateModel(type, model, prefix, includeProperties, excludeProperties, valueProvider))
            {
                throw new InvalidOperationException(string.Format(CultureInfo.CurrentUICulture, "模型更新失败。", new object[] { type.FullName }));
            }
        }

        /// <summary>
        /// 检测指定的属性是否被允许
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="includeProperties"></param>
        /// <param name="excludeProperties"></param>
        /// <returns></returns>
        private bool IsPropertyAllowed(string propertyName, string[] includeProperties, string[] excludeProperties)
        {
            // We allow a property to be bound if its both in the include list AND not in the exclude list.
            // An empty include list implies all properties are allowed.
            // An empty exclude list implies no properties are disallowed.
            bool includeProperty = (includeProperties == null) || (includeProperties.Length == 0) || includeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase);
            bool excludeProperty = (excludeProperties != null) && excludeProperties.Contains(propertyName, StringComparer.OrdinalIgnoreCase);
            return includeProperty && !excludeProperty;
        }
        */

        #endregion

        /*
        private IList<string> m_routeValueKeys;

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterContext"></param>
        protected override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            base.OnResultExecuting(filterContext);

            MvcSiteMapNode ms = SiteMap.CurrentNode as MvcSiteMapNode;

            if (ms == null)
            {
                return;
            }

            if (!(filterContext.Result is ViewResult) || !ms.IsDynamic || ms.DynamicParameters == null || ms.DynamicParameters.Count == 0)
            {
                return;
            }

            foreach (string s in ms.DynamicParameters)
            {
                if (filterContext.RouteData.Values.ContainsKey(s) && !ms.RouteValues.ContainsKey(s))
                    ms.RouteValues.Add(s, filterContext.RouteData.Values[s]);
            }

            NameValueCollection queryString = filterContext.HttpContext.Request.QueryString;
            foreach (var item in queryString.AllKeys)
            {
                if (!ms.RouteValues.ContainsKey(item))
                {
                    if (this.m_routeValueKeys == null)
                    {
                        this.m_routeValueKeys = new List<string>();
                    }
                    this.m_routeValueKeys.Add(item);
                    ms.RouteValues.Add(item, queryString[item]);
                }
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="filterContext"></param>
        protected override void OnResultExecuted(ResultExecutedContext filterContext)
        {
            if (this.m_routeValueKeys != null)
            {
                MvcSiteMapNode ms = SiteMap.CurrentNode as MvcSiteMapNode;
                if (ms != null)
                {
                    foreach (var key in this.m_routeValueKeys)
                    {
                        ms.RouteValues.Remove(key);
                    }
                }
            }

            base.OnResultExecuted(filterContext);
        }
        */
    }
}
